<!DOCTYPE html>
<html>

<head>
    <title>观察物体的不同面</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background: #f0f0f0;
        }

        #menu {
            position: absolute;
            top: 10px;
            left: 10px;
            z-index: 1;
            background: rgba(255, 255, 255, 0.95);
            padding: 15px;
            border-radius: 8px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
            min-width: 220px;
        }

        .shape-option {
            margin: 12px 0;
            display: flex;
            flex-direction: column;
        }

        .controls-row {
            display: flex;
            align-items: center;
            margin-top: 8px;
            gap: 8px;
        }

        .color-picker {
            width: 28px;
            height: 28px;
            margin-left: auto;
            cursor: pointer;
        }

        .slider {
            width: 100px;
            margin: 0;
            accent-color: #2194ce;
        }

        #instructions {
            position: absolute;
            bottom: 20px;
            left: 20px;
            background: rgba(255, 255, 255, 0.95);
            padding: 15px;
            border-radius: 8px;
            font-size: 14px;
            line-height: 1.5;
        }

        canvas {
            display: block;
            background: #e8e8e8;
        }
    </style>
</head>

<body>
    <div id="menu">
        <!-- 立方体 -->
        <div class="shape-option">
            <div style="display: flex; align-items: center;">
                <input type="checkbox" id="cube" onchange="toggleShape('cube')">
                <label for="cube" style="margin-left: 8px;">立方体</label>
                <input type="color" class="color-picker" value="#2194ce" onchange="updateColor('cube', this.value)">
            </div>
            <div class="controls-row" id="cube-controls" style="display: none;">
                <span style="font-size: 13px; color: #666;">缩放:</span>
                <input type="range" class="slider" min="0.5" max="3" step="0.1" value="1"
                    oninput="updateScale('cube', this.value)">
            </div>
        </div>

        <!-- 长方体 -->
        <div class="shape-option">
            <div style="display: flex; align-items: center;">
                <input type="checkbox" id="cuboid" onchange="toggleShape('cuboid')">
                <label for="cuboid" style="margin-left: 8px;">长方体</label>
                <input type="color" class="color-picker" value="#2194ce" onchange="updateColor('cuboid', this.value)">
            </div>
            <div class="controls-row" id="cuboid-controls" style="display: none;">
                <span style="font-size: 13px; color: #666;">缩放:</span>
                <input type="range" class="slider" min="0.5" max="3" step="0.1" value="1"
                    oninput="updateScale('cuboid', this.value)">
            </div>
        </div>

        <!-- 圆柱体 -->
        <div class="shape-option">
            <div style="display: flex; align-items: center;">
                <input type="checkbox" id="cylinder" onchange="toggleShape('cylinder')">
                <label for="cylinder" style="margin-left: 8px;">圆柱体</label>
                <input type="color" class="color-picker" value="#2194ce" onchange="updateColor('cylinder', this.value)">
            </div>
            <div class="controls-row" id="cylinder-controls" style="display: none;">
                <span style="font-size: 13px; color: #666;">缩放:</span>
                <input type="range" class="slider" min="0.5" max="3" step="0.1" value="1"
                    oninput="updateScale('cylinder', this.value)">
            </div>
        </div>

        <!-- 扁圆柱体 -->
        <div class="shape-option">
            <div style="display: flex; align-items: center;">
                <input type="checkbox" id="flatCylinder" onchange="toggleShape('flatCylinder')">
                <label for="flatCylinder" style="margin-left: 8px;">扁圆柱体</label>
                <input type="color" class="color-picker" value="#2194ce" onchange="updateColor('flatCylinder', this.value)">
            </div>
            <div class="controls-row" id="flatCylinder-controls" style="display: none;">
                <span style="font-size: 13px; color: #666;">缩放:</span>
                <input type="range" class="slider" min="0.5" max="3" step="0.1" value="1"
                    oninput="updateScale('flatCylinder', this.value)">
            </div>
        </div>

        <!-- 六角螺母 -->
        <div class="shape-option">
            <div style="display: flex; align-items: center;">
                <input type="checkbox" id="nut" onchange="toggleShape('nut')">
                <label for="nut" style="margin-left: 8px;">六角螺母</label>
                <input type="color" class="color-picker" value="#2194ce" onchange="updateColor('nut', this.value)">
            </div>
            <div class="controls-row" id="nut-controls" style="display: none;">
                <span style="font-size: 13px; color: #666;">缩放:</span>
                <input type="range" class="slider" min="0.5" max="3" step="0.1" value="1"
                    oninput="updateScale('nut', this.value)">
            </div>
        </div>
    </div>

    <div id="instructions">
        观察物体的不同面-芋芋学姐教科学<br>
        操作说明：<br>
        1. 勾选形状添加物体<br>
        2. 点击物体拖动旋转<br>
        3. 使用滑块调整大小<br>
        4. 点击色块修改颜色
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
    <script>
        // 初始化Three.js核心组件
        let scene, camera, renderer;
        let selectedObjects = [];
        let isDragging = false;
        let previousMousePosition = { x: 0, y: 0 };
        let selectedObject = null;
        const raycaster = new THREE.Raycaster();
        const mouse = new THREE.Vector2();

        // 颜色配置
        const colors = {
            cube: 0x2194ce,
            cuboid: 0x2194ce,
            cylinder: 0x2194ce,
            flatCylinder: 0x2194ce,
            nut: 0x2194ce
        };

        // 初始化场景
        function init() {
            // 创建场景
            scene = new THREE.Scene();

            // 设置相机
            camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.set(0, 2, 8);
            camera.lookAt(0, 0, 0);

            // 初始化渲染器
            renderer = new THREE.WebGLRenderer({
                antialias: true,
                alpha: true
            });
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.shadowMap.enabled = true;
            document.body.appendChild(renderer.domElement);

            // 灯光系统
            const ambientLight = new THREE.AmbientLight(0xffffff, 0.8);
            scene.add(ambientLight);

            const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
            directionalLight.position.set(10, 15, 10);
            directionalLight.castShadow = true;
            scene.add(directionalLight);

            // 事件监听
            renderer.domElement.addEventListener('mousedown', onMouseDown);
            renderer.domElement.addEventListener('touchstart', onTouchStart);
            document.addEventListener('mousemove', onMouseMove);
            document.addEventListener('touchmove', onTouchMove);
            document.addEventListener('mouseup', onMouseUp);
            document.addEventListener('touchend', onTouchEnd);
            window.addEventListener('resize', onWindowResize);
        }

        // 形状生成器
        const shapeGenerators = {
            cube: () => new THREE.BoxGeometry(1, 1, 1),
            cuboid: () => new THREE.BoxGeometry(1.5, 1, 0.8),
            cylinder: () => new THREE.CylinderGeometry(0.5, 0.5, 2, 32),
            flatCylinder: () => new THREE.CylinderGeometry(1, 1, 0.5, 32),
            nut: () => {
                const shape = new THREE.Shape();
                const radius = 1;
                const angle = (2 * Math.PI) / 6;
                shape.moveTo(radius, 0);
                for (let i = 1; i < 6; i++) {
                    shape.lineTo(
                        radius * Math.cos(angle * i),
                        radius * Math.sin(angle * i)
                    );
                }
                shape.closePath();
                const hole = new THREE.Path();
                hole.absarc(0, 0, 0.4, 0, Math.PI * 2);
                shape.holes.push(hole);
                return new THREE.ExtrudeGeometry(shape, {
                    depth: 0.4,
                    bevelEnabled: false
                });
            }
        };

        // 物体位置配置
        const positions = {
            cube: [-3, 0, 0],
            cuboid: [-1.5, 0, 0],
            cylinder: [0, 0, 0],
            flatCylinder: [1.5, 0, 0],
            nut: [3, 0, 0]
        };

        // 形状切换功能
        function toggleShape(shapeType) {
            const checkbox = document.getElementById(shapeType);
            const controls = document.getElementById(`${shapeType}-controls`);

            if (checkbox.checked) {
                const geometry = shapeGenerators[shapeType]();
                const material = new THREE.MeshPhongMaterial({
                    color: colors[shapeType],
                    shininess: 100,
                    transparent: false
                });
                const mesh = new THREE.Mesh(geometry, material);
                mesh.position.set(...positions[shapeType]);
                mesh.shapeType = shapeType;
                mesh.castShadow = true;
                mesh.receiveShadow = true;

                scene.add(mesh);
                selectedObjects.push(mesh);
                controls.style.display = 'flex';
            } else {
                selectedObjects = selectedObjects.filter(obj => {
                    if (obj.shapeType === shapeType) {
                        scene.remove(obj);
                        return false;
                    }
                    return true;
                });
                controls.style.display = 'none';
                controls.querySelector('.slider').value = 1;
            }
        }

        // 颜色更新
        function updateColor(shapeType, colorHex) {
            colors[shapeType] = parseInt(colorHex.replace('#', '0x'), 16);
            selectedObjects.forEach(obj => {
                if (obj.shapeType === shapeType) {
                    obj.material.color.set(colors[shapeType]);
                }
            });
        }

        // 缩放控制
        function updateScale(shapeType, value) {
            const scale = parseFloat(value);
            selectedObjects.forEach(obj => {
                if (obj.shapeType === shapeType) {
                    obj.scale.set(scale, scale, scale);
                }
            });
        }

        // 鼠标事件处理
        function onMouseDown(event) {
            // 转换鼠标坐标
            mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
            mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;

            // 执行射线检测
            raycaster.setFromCamera(mouse, camera);
            const intersects = raycaster.intersectObjects(selectedObjects);

            if (intersects.length > 0) {
                event.preventDefault();
                selectedObject = intersects[0].object;
                isDragging = true;
                previousMousePosition = {
                    x: event.clientX,
                    y: event.clientY
                };
            }
        }

        function onMouseMove(event) {
            if (!isDragging || !selectedObject) return;

            const deltaMove = {
                x: event.clientX - previousMousePosition.x,
                y: event.clientY - previousMousePosition.y
            };

            selectedObject.rotation.y += deltaMove.x * 0.01;
            selectedObject.rotation.x += deltaMove.y * 0.01;

            previousMousePosition = {
                x: event.clientX,
                y: event.clientY
            };
        }

        function onMouseUp() {
            isDragging = false;
            selectedObject = null;
        }

        // 触摸事件处理
        function onTouchStart(event) {
            const touch = event.touches[0];
            mouse.x = (touch.clientX / window.innerWidth) * 2 - 1;
            mouse.y = - (touch.clientY / window.innerHeight) * 2 + 1;

            raycaster.setFromCamera(mouse, camera);
            const intersects = raycaster.intersectObjects(selectedObjects);

            if (intersects.length > 0) {
                event.preventDefault();
                selectedObject = intersects[0].object;
                isDragging = true;
                previousMousePosition = {
                    x: touch.clientX,
                    y: touch.clientY
                };
            }
        }

        function onTouchMove(event) {
            if (!isDragging || !selectedObject) return;
            const touch = event.touches[0];
            const deltaMove = {
                x: touch.clientX - previousMousePosition.x,
                y: touch.clientY - previousMousePosition.y
            };

            selectedObject.rotation.y += deltaMove.x * 0.01;
            selectedObject.rotation.x += deltaMove.y * 0.01;

            previousMousePosition = {
                x: touch.clientX,
                y: touch.clientY
            };
        }

        function onTouchEnd() {
            isDragging = false;
            selectedObject = null;
        }

        // 窗口大小调整
        function onWindowResize() {
            // 这里原代码没写完，可补充完整
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        }

        // 初始化场景
        init();

        // 渲染循环
        function animate() {
            requestAnimationFrame(animate);
            renderer.render(scene, camera);
        }
        animate();
    </script>
</body>

</html>